__author__ = 'sdjkx'

# encoding:utf-8
import requests
import os
import json
import base64

try:
  import xml.etree.cElementTree as ET
except ImportError:
  import xml.etree.ElementTree as ET

from PyQt5.QtWidgets import QFileDialog, QMessageBox
from libs.ustr import ustr
from libs.ImageLabelData import ImageLabelData


class EasyDlUpload:

    def __init__(self,labelImg, fileInfoManager):
        self.labelImg = labelImg
        self.fileInfoManager = fileInfoManager

        self.imageDir = ""
        self.xmlDir = ""
        self.tokenUrl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=ozkOOLXX6o1YE3vRWX8nTp3S&client_secret=qfr4VVaAS1jZxpxlh4pw5vyOenpFiuNr"
        self.easyDlUrl = "https://aip.baidubce.com/rpc/2.0/easydl/dataset/addentity"
        self.modelId = 102390
        self.access_token = ""

        self.headers = {'Content-Type': 'application/json'}

    def upload(self, label_cn_en, lastOpenDir = "" ):
        if(lastOpenDir != ""):
            ret = QMessageBox.question(self.labelImg, '提示', "是要上传目录【"+lastOpenDir+"】的文件吗？", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if ret == QMessageBox.Yes:
                self.imageDir = lastOpenDir
            else:
                self.imageDir = ""

        if self.imageDir == "":
            lastOpenDir = ustr(QFileDialog.getExistingDirectory(self.labelImg,
                                                         '选择要上传的目录', lastOpenDir,
                                                         QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks))

            ret = QMessageBox.question(self.labelImg, '提示', "是要上传目录【"+lastOpenDir+"】的文件吗？", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if ret == QMessageBox.Yes:
                self.imageDir = lastOpenDir
            else:
                self.imageDir = ""

        if self.imageDir == "":
            return

        self.xmlDir = self.getXmlPath(self.imageDir)
        if self.xmlDir == "":
            return

        if not self.imageDir.endswith("/"):
            self.imageDir += "/"

        self.sendFile(label_cn_en)

    def getXmlPath(self, filePath = ""):
        index = filePath.rfind("/")
        xmlDir = filePath[0:index]+ "/Annotations/"
        if not os.path.exists(xmlDir):
            QMessageBox.information(self.labelImg, "","XML文件目录【" + xmlDir+ "】不存在")
            return ""

        return xmlDir

    def sendFile(self, label_cn_en):
        self.getBaiduToken()
        self.label_cn_en = label_cn_en

        if(self.access_token == ""):
            return

        for filename in os.listdir(self.imageDir):
            # filename = self.getFileName(filepath)
            filePath = self.imageDir + filename
            fileid = 0
            fileStatus = 0
            userId = ""

            if filename.find('-') < 0:
                userId, fileid, fileStatus = self.fileInfoManager.queryFile(filename)
                if fileStatus == 4:
                    continue
                # sql = self.queryFileSql.format(filename)
                # results = self.mydb.executeSql(sql)
                # if len(results) > 0:
                #     userid = results[0][0]
                #     fileid = results[0][1]
                #     fileStatus = results[0][2]
                #     if fileStatus == 4:
                #         continue

            xmlFilePath = self.xmlDir + filename.split(".")[0] + ".xml"

            # 如果 xml 文件不存在，则跳过
            if not os.path.exists(xmlFilePath):
                print("图片文件"+filePath+"没有对应的XML文件")
                continue
            if fileid == 0:
                userId = "100007"
                fileSize = 1
                self.fileInfoManager.insertFile(userId, filename, fileSize)
                
            # 获取XML文件内容
            xmlJson = self.getXmlJson(xmlFilePath)
            if xmlJson == "":
                return

            # 读取图片文件，保存为 base64字符串
            entity_content = self.readFile(filePath)

            # 上传文件
            # 字段	必选	类型	说明
            # type	是	string	数据集类型，可包括： IMAGE_CLASSIFICATION, OBJECT_DETECTION, IMAGE_SEGMENTATION, SOUND_CLASSIFICATION, TEXT_CLASSIFICATION
            # 分别对应：图像分类、物体检测、图像分割、声音分类、文本分类
            # dataset_id	是	number	数据集ID
            # appendLabel	否	boolean	确定添加标签/分类的行为：追加(true)、替换(false)。默认为追加(true)。
            # entity_content	是	string	type为 IMAGE_CLASSIFICATION/OBJECT_DETECTION/IMAGE_SEGMENTATION/SOUND_CLASSIFICATION时，填入图片/声音的base64编码；type为TEXT_CLASSIFICATION时，填入utf-8编码的文本。内容限制为：图像分类base64前10M；物体检测base64前10M；图像分割base64前10M；声音分类base64前4M，声音时长1~15秒；文本分类10000个汉字
            # entity_name	是	string	文件名
            # labels	否	array(object)	标签/分类数据。若为空，则只上传图片，不上传标签/分类。若不为空，则应在数组中包含以下前面带+的参数
            # +label_name	是	string	标签/分类名称（由数字、字母、中划线、下划线组成），长度限制20B
            # +left	否	number	物体检测时需给出，标注框左上角到图片左边界的距离(像素)
            # +top	否	number	物体检测时需给出，标注框左上角到图片上边界的距离(像素)
            # +width	否	number	物体检测时需给出，标注框的宽度(像素)
            # +height	否	number	物体检测时需给出，标注框的高度(像素)
            params = {
                'type':'OBJECT_DETECTION',
                "dataset_id":self.modelId,
                "appendLabel":True,
                "entity_content": entity_content,
                "entity_name":filename,
                "labels": xmlJson
            }
            params = json.dumps(params)
            response = requests.post(self.easyDlUrl + "?access_token=" + self.access_token,
                                     headers = self.headers,
                                     data = params)

            # print(response.content)
            data = str(response.content)
            # print("图片上传后的log_id = " + data["log_id"])
            if data.find("log_id") >= 0:
                self.fileInfoManager.updateFileStatus(userId, filename, 4)
            else:
                 print("图片文件"+filePath+"上传失败")


    def getBaiduToken(self):
        # client_id 为官网获取的AK， client_secret 为官网获取的SK
        response = requests.get(self.tokenUrl)
        if response:
            print(response.json())
            # data = json.load(response.json())
            data = response.json()
            self.access_token = data["access_token"]
        else:
            print("没有获取到Token")

    def getFileName(self, filePath):
        fileArr = str(filePath).split("/")
        return fileArr[len(fileArr) - 1]


    def getXmlJson(self, xmlFilePath):
        tree = ET.parse(xmlFilePath)     #打开xml文档
        root = tree.getroot()         #获得root节点

        labels = []
        for object in root.findall('object'): #找到root节点下的所有object节点
            label_name = object.find('name').text   #子节点下节点name的值
            if self.label_cn_en.__contains__(label_name):
                en_name = self.label_cn_en[label_name]
            else:
                return ""

            bndbox = object.find('bndbox')      #子节点下属性bndbox的值

            xmin = int(bndbox.find('xmin').text)
            ymin = int(bndbox.find('ymin').text)
            xmax = int(bndbox.find('xmax').text)
            ymax = int(bndbox.find('ymax').text)

            labels.append({"label_name":en_name,"left": xmin,"top": ymin, "width": xmax - xmin, "height": ymax - ymin})
            # labels.append(json.dump(label_name, left = xmin, top = ymin, width = xmax - xmin, height = ymax - ymin))

        msg = json.dumps(labels)
        return msg

    def readFile(self, filePath):
        with open(filePath, 'rb') as f:
            base64_data = base64.b64encode(f.read())
            return base64_data.decode("UTF8")
